package com.jinyou.utils.common;

import org.apache.commons.lang.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DateUtils {

    public static final Long oneDayMills = Long.valueOf(86400000L);
    public static final Long oneHourMills = Long.valueOf(3600000L);

    //获取当前时间的时间戳
    // Jahnke 2018-04-18 10:08  更改获取当前时间的方式
    public static long getCurrTime() {
        return System.currentTimeMillis();
    }

    // Jahnke   时间格式 线程安全
    public final static ThreadLocal<DateFormat> sdfDateSeconds = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmmss", Locale.SIMPLIFIED_CHINESE);
        }
    };
    public final static ThreadLocal<DateFormat> sdfDate = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd", Locale.SIMPLIFIED_CHINESE);
        }
    };
    public final static ThreadLocal<DateFormat> sdfDateTime = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE);
        }
    };
    public final static ThreadLocal<DateFormat> sdfDatTimeMinate = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.SIMPLIFIED_CHINESE);
        }
    };
    public final static ThreadLocal<DateFormat> sdfSeconds = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyMMddHHmmss", Locale.SIMPLIFIED_CHINESE);
        }
    };
    public final static ThreadLocal<DateFormat> sdfTime = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd", Locale.SIMPLIFIED_CHINESE);
        }
    };
    public final static ThreadLocal<DateFormat> sdfHourTime = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat("HH:mm", Locale.SIMPLIFIED_CHINESE);
        }
    };

    public static final SimpleDateFormat sdfYearMonth = new SimpleDateFormat("yyyyMMdd");
    public static final SimpleDateFormat sdfYearMonthTime = new SimpleDateFormat("yyyyMMddHHmmss");
    //    public static final SimpleDateFormat sdfTime = new SimpleDateFormat("yyyyMMdd");
//    public static final SimpleDateFormat sdfDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE);
    public static final SimpleDateFormat sdfDateTimeMills = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss sss", Locale.SIMPLIFIED_CHINESE);

    // Jahnke  获取某天的开始时间戳
    public static Long getStartTime(Date date, int days) {
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.DAY_OF_MONTH, days);
        now.set(Calendar.HOUR_OF_DAY, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        return Long.valueOf(now.getTime().getTime());
    }

    // Jahnke  获取某天的结束时间戳
    public static Long getEndTime(Date date, int days) {
        Calendar now = Calendar.getInstance();
        now.setTime(date);
        now.add(Calendar.DAY_OF_MONTH, days);
        now.set(Calendar.HOUR_OF_DAY, 23);
        now.set(Calendar.MINUTE, 59);
        now.set(Calendar.SECOND, 59);
        return Long.valueOf(now.getTime().getTime());
    }

    /**
     * 获取当前时间在今年的第几周
     *
     * @return
     */
    public static int weekOfYear(Date date) {
        Calendar c = Calendar.getInstance();
        if (date == null) {
            date = new Date();
        }
        c.setTime(date);
        return c.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 得到某一年周的总数
     *
     * @param year
     * @return
     */
    public static int getMaxWeekNumOfYear(int year) {
        Calendar c = Calendar.getInstance();
        c.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
        return c.getWeekYear();
    }
//
//    /**
//     * 取得当前日期所在周的第一天--周一
//     *
//     * @param date
//     * @return
//     */
//    public static Date getFirstDayOfWeek(Date date) {
//        Calendar c = Calendar.getInstance();
//        if (date != null) {
//            c.set(date.getYear(), date.getMonth(), date.getDate());
//        }
//        c.setFirstDayOfWeek(Calendar.MONDAY);
//        c.setTime(new Date());
//        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek()); // Monday
//        return c.getTime();
//    }
//
//    public static Date getLastDayOfWeek(Date date) {
//        Calendar c = Calendar.getInstance();
//        c.setTime(getFirstDayOfWeek(date));
//        c.add(Calendar.DATE, 6);
//        return c.getTime();
//    }

    /**
     * 根据日期获得周几
     *
     * @param date
     * @return
     */
    public static int DayOfWeekYear(Date date) {
        Calendar c = Calendar.getInstance();
        if (date == null) {
            date = new Date();
        }
        c.setTime(date);
        return c.getWeeksInWeekYear();
    }


    //获取当前年月  201612
    public static String getCurrentYearMonth() {
        return sdfYearMonth.format(new Date());
    }

    //获取当前日期  20170831
    public static String getCurrentDate() {
        return sdfTime.get().format(new Date());
    }

    //获取当前日期  yyyy-MM-dd HH:mm:ss
    public static String getCurrentDateTime() {
        return sdfDateTime.get().format(new Date());
    }

    //获取当前日期  yyyy-MM-dd HH:mm:ss
    public static String getCurrentDateTimeMills() {
        return sdfDateTimeMills.format(new Date());
    }

    //获取当前日期  yyyy-MM-dd HH:mm:ss
    public static String getCurrentDateTimeMillsTrim() {
        return sdfYearMonthTime.format(new Date());
    }

    //获取当前日期  yyyyMMddHHmmss
    public static String getDateTimeMillsTrim(Long timestamp) {
        return sdfDateSeconds.get().format(timestamp);
    }

    // 获取时间戳的时间
    public static String getCurrentHourTime() {
        return sdfHourTime.get().format(new Date());
    }

    public static String getTimestampHourTime(Long timestamp) {
        return sdfHourTime.get().format(new Date(timestamp));
    }

    //根据时间戳获取该日的开始时间戳，结束时间戳
    public static StartEndOfDayTimestamp getStartEndTimestamp(Long timestamp) {
        //获取时间戳的日期
        String day = timeStampToDate(timestamp);
        String start = datetimeToStamp(day + " 00:00:00");
        String end = datetimeToStamp(day + " 23:59:59");

        StartEndOfDayTimestamp startEndOfDayTimestamp = new StartEndOfDayTimestamp();
        startEndOfDayTimestamp.startTimestamp = Long.parseLong(start);
        startEndOfDayTimestamp.endTimestamp = Long.parseLong(end) + 1000;
//        System.out.println(start);
//        System.out.println(Long.parseLong(end) + 1000 + "");

        return startEndOfDayTimestamp;
    }

    //获取该日的开始时间戳
    public static Long getTodayStartTimestamp() {
        //获取时间戳的日期
        String day = timeStampToDate(getCurrTime());
        return Long.parseLong(datetimeToStamp(day + " 00:00:00"));
    }

    public static Long getDayStartTimestamp(Long time) {
        //获取时间戳的日期
        String day = timeStampToDate(time);
        return Long.parseLong(datetimeToStamp(day + " 00:00:00"));
    }

    public static Long getAfterDaysTimestamp(int days) {
        if (days <= 0) {
            return 0l;
        }
        return getCurrTime() + days * 24 * 60 * 60 * 1000;
    }

    public static Long getAfterDaysTimestamp(Long days) {
        if (days <= 0) {
            return 0l;
        }
        return getCurrTime() + days * 24 * 60 * 60 * 1000;
    }


    // 获多少天前的时间戳
    public static Long getPreDaysOfTimestamp(Long days) {
        if (null == days) {
            days = 0l;
        }
        return getCurrTime() - days * 24 * 60 * 60 * 1000;
    }

    //时间戳转日期
    public static String timeStampToDate(long timeStamp) {
        Date date = new Date(timeStamp);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = simpleDateFormat.format(date);
        return dateStr;
    }

    //时间戳转时间
    public static String timeStampToDatetime(long timeStamp) {
        Date date = new Date(timeStamp);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = simpleDateFormat.format(date);
        return dateStr;
    }

    //时间转换为时间戳
    public static String datetimeToStamp(String s) {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }

    public static class StartEndOfDayTimestamp {
        public Long startTimestamp;
        public Long endTimestamp;
    }

    //判断时间戳是否是当期月
    public static boolean isNowMonth(long timestamp) {
        SimpleDateFormat df = new SimpleDateFormat("yyyyMM");//设置日期格式
        String date = df.format(timestamp);
        String now = df.format(new Date());
        if (now.equals(date)) {
            return true;
        } else {
            return false;
        }
    }

    // 获取某月的第一天
    public static Date getFirstDayOfMonth(Date date) {
        LocalDate today = date2LocalDate(date);
        LocalDate firstday = LocalDate.of(today.getYear(), today.getMonth(), 1);

        return localDate2Date(firstday);
    }

    //本月的最后一天
    public static Date getLastDayOfMonth(Date date) {
        LocalDate today = date2LocalDate(date);
        LocalDate lastDay = today.with(TemporalAdjusters.lastDayOfMonth());

        return localDate2Date(lastDay);
    }

    // localDate转date
    public static Date localDate2Date(LocalDate localDate) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDate.atStartOfDay(zoneId);

        Date date = Date.from(zdt.toInstant());
        return date;
    }

    // date转localdate
    public static LocalDate date2LocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();

        // atZone()方法返回在指定时区从此Instant生成的ZonedDateTime。
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        return localDate;
    }

    // 获取本月的某天开始时间
    public static Date getMonthDayByDay(int day) {
        Calendar now = Calendar.getInstance();
        now.set(Calendar.DAY_OF_MONTH, day);
        now.set(Calendar.HOUR_OF_DAY, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        return now.getTime();
    }

    // 获取下个月的某天开始时间
    public static Date getNextMonthDayByDay(int day) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.MONTH, 1);
        now.set(Calendar.DAY_OF_MONTH, day);
        now.set(Calendar.HOUR_OF_DAY, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        return now.getTime();
    }

    // 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String[] args) {
//        System.out.println(sdfDate.format(getLastDayOfWeek(new Date())));

//        isNowMonth(1498838400000l);
//        System.out.println(getCurrentYearMonth());

        System.out.println(getTimestampHourTime(1591059212000l));
    }

    public static boolean isSameDate(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        boolean isSameYear = cal1.get(1) == cal2.get(1);
        boolean isSameMonth = isSameYear && cal1.get(2) == cal2.get(2);
        boolean isSameDate = isSameMonth && cal1.get(5) == cal2.get(5);
        return isSameDate;
    }

    // 获取uuid 标识
    public static String getUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    //-------------------
    // 获取当前时间的时、分，转化成数字
    public static Long getNowMinSecLon() {
//        Calendar now = Calendar.getInstance();
//        // 小时为24点特殊处理
//        int hour = now.get(Calendar.HOUR_OF_DAY);
//        if (hour == 0) {
//            hour = 24;
//        }
//        // 分钟为个位数特殊处理
//        int mI = now.get(Calendar.MINUTE);
//        String minute = "";
//        if (mI < 10) {
//            minute = "0" + mI;
//        } else {
//            minute = "" + mI;
//        }
//
//        String nowTimeStr = hour + ":" + minute;
//        nowTimeStr = nowTimeStr.replace(":", "");
//        return Long.parseLong(nowTimeStr);

        String time = getCurrentHourTime();
        time = time.replace(":", "");
        return Long.parseLong(time);
    }

    // 将时间戳的时、分转化成数字
    public static Long convertTimestampToMinSecLong(Long timestamp) {
        String time = getTimestampHourTime(timestamp);
        time = time.replace(":", "");
        return Long.parseLong(time);
    }

    // 是否在多个时间段内
    public static boolean isInTimeScope(String timeStr, Long targetTime) {
        if (ValidateUtil.isNull(timeStr) || "null".equalsIgnoreCase(timeStr) || "undefined".equalsIgnoreCase(timeStr)) {
            return false;
        }
        Boolean inTheTime = false;// 是否在时间段内
        String[] timeArr = timeStr.split(",");
        for (int j = 0; j < timeArr.length; j++) {
            String timStr = timeArr[j];
            if (null == timStr) {
                continue;
            }
            if (ValidateUtil.isNull(timStr) || "null".equalsIgnoreCase(timStr) || "undefined".equalsIgnoreCase(timStr)) {
                continue;
            }

            // 每段时间
            String[] timePoint = timStr.split("-");
            if (null == timePoint || timePoint.length < 1) {
                continue;
            }
            Long starTime = toLong(timePoint[0].replace(":", ""));
            if (null == starTime) {
                continue;
            }
            Long endTime = toLong(timePoint[1].replace(":", ""));
            if (null == endTime) {
                continue;
            }
            if (0 == starTime) {
                starTime = 2400l;
            }
            if (0 == endTime) {
                endTime = 2400l;
            }


            // 开始时间 等于结束时间 表示全天营业
            if (0 == starTime - endTime) {
                // 全天上班  直接上班
                inTheTime = true;
            }

            // 营业时间在营业范围内则上班
            if (endTime < starTime) {   // 开始时间大于结束时间  例：24:00-2:00
//                                当前时间 24：25    1:00分两种情况
                if ((targetTime >= starTime && targetTime >= endTime) || (starTime >= targetTime && endTime >= targetTime)) {
                    // 此刻需营业ing
                    inTheTime = true;
                }

            } else {  // 开始时间小于结束时间  例：8:00-9:00
                if (targetTime >= starTime && endTime >= targetTime) {
                    // 此刻需营业ing
                    inTheTime = true;
                }
            }
            if (inTheTime) {
                // 初始是需要下班，遇到需要上班的则不用继续循环，直接去上班
                break;
            }
        }
        return inTheTime;
    }


    /**
     * 比较一个 HH:mm 是否在一个时间段内
     * 如：14:33:00 是否在 09:30:00 和 12:00:00 内
     */
    public static boolean isInTimeScope(String time, String start, String end) {
        if (ValidateUtil.isNull(time)) {
            return false;
        }
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        Date now = null;
        Date beginTime = null;
        Date endTime = null;
        try {
            now = df.parse(time);
            beginTime = df.parse(start);
            endTime = df.parse(end);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return belongCalendar(now, beginTime, endTime);
    }


    /**
     * 判断时间是否在时间段内
     */
    public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) {
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(beginTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        return date.after(begin) && date.before(end);
    }



    private static Long toLong(String val) {
        if (ValidateUtil.isNull(val)) {
            return 0l;
        }
        if (!isNumber(val)) {
            return null;
        }
        return Long.parseLong(val);
    }

    private static boolean isNumber(String value) {
        String regEx = "^-?[0-9]+$";
        Pattern pat = Pattern.compile(regEx);
        Matcher mat = pat.matcher(value);
        if (mat.find()) {
            return true;
        } else {
            return false;
        }
    }


}
